﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Resources;
using System.IO;
namespace NFinal.Middleware.Resources.Helper
{
    public class SimpleResponse
    {
        public string requestPath;
        public string contentType;
        public byte[] content;

        public SimpleResponse(ResourcesXmlConfig xmlConfig,string requestPath,byte[] content)
        {
            string fileExtension = Path.GetExtension(requestPath);
            var mimeMap= xmlConfig.staticContent.mimeMaps.FirstOrDefault((mime) => { return mime.fileExtension == fileExtension; });
            if (mimeMap != null)
            {
                this.contentType = mimeMap.mimeType;
            }
            else
            {
                this.contentType = "application/octet-stream";
            }
            this.requestPath = requestPath;
            this.content = content;
        }
    }
    
    public class ResourcesReader
    {
        public static SortedDictionary<string, SimpleResponse> sortedDictionary;
        public Assembly assembly;
        public ResourcesReader(Assembly assembly)
        {
            this.assembly = assembly;
        }
        public void ReadToMemory(ResourcesXmlConfig config)
        {
            sortedDictionary = new SortedDictionary<string, SimpleResponse>();
            if (config.textResources.Length > 0)
            {
                for (int i = 0; i < config.textResources.Length; i++)
                {
                    string resourceName =new AssemblyName( assembly.FullName).Name + "." + config.textResources[i].fileName.Replace('/','.');
                    using (System.IO.Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
                    {
                        using (ResourceReader resourceReader = new ResourceReader(resourceStream))
                        {
                            foreach (System.Collections.DictionaryEntry resource in resourceReader)
                            {
                                string key = (string)resource.Key;
                                if (key[0] != '/')
                                {
                                    key = '/' + key;
                                }
                                string requestPath=  GetRequestPath(key, config.textResources[i].includes);
                                sortedDictionary.Add(requestPath,
                                    new SimpleResponse(config, requestPath,
                                        System.Text.Encoding.UTF8.GetBytes((string) resource.Value)));
                            }
                        }
                       
                    }
                }
                for (int i = 0; i < config.streamResources.Length; i++)
                {
                    string resourceName =new AssemblyName(assembly.FullName).Name + "." + config.streamResources[i].fileName.Replace('/','.');
                    using (System.IO.Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
                    {
                        using (ResourceReader resourceReader = new ResourceReader(resourceStream))
                        {
                            foreach (System.Collections.DictionaryEntry resource in resourceReader)
                            {
                                string key = (string)resource.Key;
                                if (key[0] != '/')
                                {
                                    key = '/' + key;
                                    byte[] buffer=Convert.FromBase64String((string)resource.Value);
                                    string requestPath = GetRequestPath(key, config.streamResources[i].includes);
                                    sortedDictionary.Add(requestPath,
                                        new SimpleResponse(config, requestPath,
                                            buffer));
                                }
                            }
                        }
                    }
                }
            }
        }
        private string GetRequestPath(string relativeFilePath,Include[] includes)
        {
            if (includes.Length > 0)
            {
                for (int i = 0; i < includes.Length; i++)
                {
                    if (relativeFilePath.StartsWith(includes[i].localPath))
                    {
                        if (includes[i].requestPath.Length > 1)
                        {
                            return includes[i].requestPath + relativeFilePath;
                        }
                        else
                        {
                            return relativeFilePath;
                        }
                    }
                }
            }
            return relativeFilePath;
        }
        public void ReadToLocal(string resourceName, string directoryRoot)
        {
            var resourceInfo= assembly.GetManifestResourceInfo(resourceName);
            string[] resouceFileNames= assembly.GetManifestResourceNames();
            string[] pathArray = null;
            string[] path = null;
            foreach (var resouceFileName in resouceFileNames)
            {
                using (System.IO.Stream resouceStream = assembly.GetManifestResourceStream(resouceFileName))
                {
                    ResourceReader resourceReader = new ResourceReader(resouceStream);
                    foreach (System.Collections.DictionaryEntry resource in resourceReader)
                    {
                        string key = (string)resource.Key;
                        if (key[0] != '/')
                        {
                            key = '/' + key;
                        }
                        pathArray = (key).Split(new[] { '/' });
                        pathArray[0] = directoryRoot;
                        string fileName = Path.Combine(pathArray);
                       
                        string directoryName = Path.GetDirectoryName(fileName);
                        if (!Directory.Exists(directoryName))
                        {
                            Directory.CreateDirectory(directoryName);
                        }
                        string extension = Path.GetExtension(fileName);
                        bool isText = ResourcesHelper.IsTextResouce(extension);
                        if (isText)
                        {
#if NETCORE
                            File.WriteAllText(fileName,(string)resource.Value);
#else
                            using (StreamWriter streamWriter = new StreamWriter(fileName, false))
                            {
                                streamWriter.Write((string)resource.Value);
                            }
#endif
                        }
                        else
                        {
                            using (FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Read))
                            {
#if NETCORE
                                byte[] buffer = System.Convert.FromBase64String((string) resource.Value);
#else
                                byte[] buffer = System.Convert.FromBase64String((string)resource.Value);
#endif
                                fileStream.Write(buffer, 0, buffer.Length);
                            }
                        }
                    }
                }
            }
            
        }
    }
}
